import { defineStore } from "pinia";
import { ref } from "vue";
import axios from "axios";

interface Resp<T> {
  error?: string;
  data?: T;
}

interface AddReq {
  uri: string;
  cate: Category;
  dir?: string;
  name?: string;
}

enum Status {
  Waiting = "Waiting",
  Active = "Active",
  Pause = "Pause",
  Seeding = "Seeding",
  Complete = "Complete",
  Error = "Error",
}

enum Category {
  File = "File",
  Magnet = "Magnet",
  BitTorrent = "BitTorrent",
}

interface Task {
  id: number;
  gid: string;
  name: string;
  status: Status;
  category: Category;
  created_at: number;
  dir: string;
  files: File[];
  connections: number;
  download_speed: number;
  total_length: number;
  completed_length: number;
  upload_speed: number;
  upload_length: number;
  followed_by?: string[];
  following?: string;
  mode?: string;
  error_code?: string;
  seeder?: boolean;
}

interface File {
  index: number;
  path: string;
  completed_length: number;
  length: number;
  selected: boolean;
}

interface SelectFileReq {
  gid: string;
  select_file: string;
}

interface QueryReq {
  status?: Status;
  name?: string;
}

const useApisStore = defineStore("apis", () => {
  const instance = axios.create({
    baseURL: "/api",
    headers: {
      "Content-Type": "application/json",
    },
    timeout: 5000,
  });

  const version = ref<string>("unknown");
  const tasks = ref<Task[]>([]);
  const selectStatus = ref<Status | "all">("all");

  async function getVersion() {
    if (version.value != "unknown") {
      return;
    }
    const { data } = await instance.get<Resp<string>>("/aria2/version");
    if (data.error) {
      return Promise.reject(data.error);
    }
    if (data.data) {
      version.value = data.data;
    }
  }

  async function addTask(req: AddReq) {
    const { data } = await instance.post<Resp<string>>("/task/add", req);
    if (data.error) {
      return Promise.reject(data.error);
    }
    return Promise.resolve(data.data || "任务已创建");
  }

  async function selectFile(req: SelectFileReq) {
    const { data } = await instance.post<Resp<string>>("/select/file", req);
    if (data.error) {
      return Promise.reject(data.error);
    }
    return Promise.resolve(data.data || "文件已更新");
  }

  async function pauseTask(id: number) {
    const { data } = await instance.patch<Resp<string>>(`/task/${id}/pause`);
    if (data.error) {
      return Promise.reject(data.error);
    }
    return Promise.resolve(data.data || "任务已暂停");
  }

  async function startTask(id: number) {
    const { data } = await instance.patch<Resp<string>>(`/task/${id}/start`);
    if (data.error) {
      return Promise.reject(data.error);
    }
    return Promise.resolve(data.data || "任务已开始");
  }

  async function deleteTask(id: number) {
    const { data } = await instance.delete<Resp<string>>(`/task/${id}`);
    if (data.error) {
      return Promise.reject(data.error);
    }
    return Promise.resolve(data.data || "任务已删除");
  }

  async function clearTask(gids: string[]) {
    const { data } = await instance.post<Resp<string>>("/task/clear", { gids });
    if (data.error) {
      return Promise.reject(data.error);
    }
    return Promise.resolve(data.data || "任务已清除");
  }

  async function getTasks(params?: QueryReq) {
    try {
      const { data } = await instance.get<Resp<Task[]>>("/tasks", { params });
      if (data.error) {
        return Promise.reject(data.error);
      }
      if (data.data) {
        tasks.value = data.data;
      }
    } catch (error) {
      return Promise.reject(error);
    }
  }

  function startTaskNotify() {
    const source = new EventSource("/api/task/notify");
    source.onmessage = (event: MessageEvent) => {
      const t: Task = JSON.parse(event.data);
      const idx = tasks.value.findIndex((item) => item.id == t.id);
      if (idx >= 0) {
        if (selectStatus.value === "all" || selectStatus.value === t.status) {
          tasks.value[idx] = t;
        } else {
          tasks.value.splice(idx, 1);
        }
      } else {
        if (selectStatus.value === "all" || selectStatus.value === t.status) {
          tasks.value = [t, ...tasks.value];
        }
      }
    };
  }

  return {
    version,
    tasks,
    selectStatus,
    getVersion,
    addTask,
    getTasks,
    selectFile,
    pauseTask,
    startTask,
    deleteTask,
    clearTask,
    startTaskNotify,
  };
});

export { useApisStore, Status, Category };
export type { AddReq, Task, File, SelectFileReq, QueryReq };
